package com.cstor.liang.service;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.cstor.liang.mapper.UserMapper;
import com.cstor.liang.pojo.entity.User;
import com.cstor.liang.pojo.other.UserModifyVo;
import com.cstor.liang.pojo.other.UserVo;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.io.UnsupportedEncodingException;
import java.util.List;

/**
 * Created by ahdkk on 2017/6/17.
 */
@Service
@Transactional
public class UserService extends BaseService<User>{

    @Autowired
    private UserMapper userMapper;

    /**
     * 用户登录
     * @param username 用户名
     * @param password 密码
     * @return 加密的Token
     */
    @Transactional(readOnly = true)
    public String login(String username, String password){
        //查询用户信息
        Example example = new Example(User.class);
        example.createCriteria()
                .andEqualTo("username",username)
                .andEqualTo("isDelete", 0);
        List<User> list = userMapper.selectByExample(example);
        User user = list.size() > 0 ? list.get(0) : null;
        if(null == user || user.getEnabled() == 0)
            throw new RuntimeException("账号不存在或已禁用");

        //密码验证
        if (!password.equals(user.getPassword()))
            throw new RuntimeException("密码错误");

        //计算Token
        try {
            return JWT.create()
                    .withClaim("username", user.getUsername())
                    .sign(Algorithm.HMAC256(user.getPassword()));
        } catch (UnsupportedEncodingException exception){
            //UTF-8 encoding not supported
            throw new RuntimeException("不支持UTF-8");
        } catch (JWTCreationException exception){
            //Invalid Signing configuration / Couldn't convert Claims.
            throw new RuntimeException("Token签名出错");
        }
    }

    /**
     * 修改用户信息
     * @param userModifyVo 待修改的信息
     * @param user 当前登录的用户信息
     * @param isAdmin 是否为管理员
     */
    public void updateUserInfo(UserModifyVo userModifyVo, User user, boolean isAdmin) {
        //有修改数据的信息将被修改，否则不修改

        user.setNickname(userModifyVo.getNickname() != null ?
                userModifyVo.getNickname() : user.getNickname());
        user.setTelephone(userModifyVo.getTelephone() != null ?
                userModifyVo.getTelephone() : user.getTelephone());
        user.setPassword(userModifyVo.getPassword() != null ?
                userModifyVo.getPassword() : user.getPassword());
        user.setRegionId(userModifyVo.getRegionId() != null ?
                userModifyVo.getRegionId() : user.getRegionId());
        user.setAddress(userModifyVo.getAddress() != null ?
                userModifyVo.getAddress() : user.getAddress());

        //查看是否为管理员修改，只有管理员才能修改敏感数据，例如角色类型、锁定、删除

        if (isAdmin){
            user.setRoleId(userModifyVo.getRoleId() != null ?
                    userModifyVo.getRoleId() : user.getRoleId());
            user.setEnabled(userModifyVo.getEnabled() != null ?
                    userModifyVo.getEnabled() : user.getEnabled());
            user.setIsDelete(userModifyVo.getIsDelete() != null ?
                    userModifyVo.getIsDelete() : user.getIsDelete());
        }

        //修改用户信息

        if (1 != userMapper.updateByPrimaryKey(user))
            throw new RuntimeException("修改用户信息失败");
    }

    /**
     * 修改用户信息
     * @param userModifyVo 待修改的信息
     * @param userId 被修改用户的id
     */
    public void updateUserInfo(UserModifyVo userModifyVo, Long userId) {
        //查找指定id的用户
        User user = userMapper.selectByPrimaryKey(userId);
        if (user == null)
            throw new RuntimeException("被修改用户不存在");

        updateUserInfo(userModifyVo, user, true);
    }

    /**
     * 新增一个用户
     * @param userVo 用户信息
     */
    public void add(UserVo userVo) {
        //验证：用户名必须唯一
        Example example = new Example(User.class);
        example.createCriteria().andEqualTo("username", userVo.getUsername());
        if (userMapper.selectCountByExample(example) > 0)
            throw new RuntimeException("用户名已存在");

        //注册用户
        User u = new User();
        u.setNickname(userVo.getNickname());
        u.setRegionId(userVo.getRegionId());
        u.setAddress(userVo.getAddress());
        u.setTelephone(userVo.getTelephone());
        u.setUsername(userVo.getUsername());
        u.setPassword(userVo.getPassword());
        u.setRoleId(userVo.getRoleId());
        u.setEnabled(1);
        u.setIsDelete(0);
        if (1 != userMapper.insert(u))
            throw new RuntimeException("新增用户失败");

    }

    /**
     * 删除一个用户
     * @param id
     */
    public void delete(Long id) {
        if (1 != userMapper.deleteByPrimaryKey(id))
            throw new RuntimeException("删除用户失败");
    }

    /**
     * 列出所有用户
     * @param pageIndex 页码
     * @param pageSize  数量
     * @return
     */
    @Transactional(readOnly = true)
    public List<User> list(Integer pageIndex, Integer pageSize) {
        PageHelper.startPage(pageIndex, pageSize);
        return userMapper.selectAll();
    }

    /**
     * 根据角色类型，查询所有用户
     *
     * @param roleId    角色类型id
     * @param pageIndex 页码
     * @param pageSize  数量
     * @return
     */
    @Transactional(readOnly = true)
    public List<User> listByRole(Integer roleId, Integer pageIndex, Integer pageSize) {
        PageHelper.startPage(pageIndex, pageSize);
        Example example = new Example(User.class);
        example.createCriteria().andEqualTo("roleId", roleId);
        return userMapper.selectByExample(example);
    }

    /**
     * 根据关键字，查找所有用户名或昵称符合的用户
     *
     * @param keyword   关键字
     * @param pageIndex 页码
     * @param pageSize  数量
     * @return
     */
    @Transactional(readOnly = true)
    public List<User> listByKeyword(String keyword, Integer pageIndex, Integer pageSize) {
        PageHelper.startPage(pageIndex, pageSize);
        Example example = new Example(User.class);
        example.createCriteria()
                .orLike("username", "%" + keyword + "%")
                .orLike("nickname", "%" + keyword + "%");
        return userMapper.selectByExample(example);
    }


}
